home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-01 | 72.3 KB | 2,402 lines |
- Newsgroups: comp.sources.unix
- From: madler@cco.caltech.edu (Mark Adler)
- Subject: v25i143: zip - file compression/archive tool, Part02/07
- Sender: unix-sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: madler@cco.caltech.edu (Mark Adler)
- Posting-Number: Volume 25, Issue 143
- Archive-Name: zip/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 7)."
- # Contents: im_lm.asm implode.c shrink.c util.c zip.h zipnote.c
- # zipup.c
- # Wrapped by vixie@cognition.pa.dec.com on Sun Mar 1 18:57:37 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'im_lm.asm' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'im_lm.asm'\"
- else
- echo shar: Extracting \"'im_lm.asm'\" \(9944 characters\)
- sed "s/^X//" >'im_lm.asm' <<'END_OF_FILE'
- X;
- X; Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X; Permission is granted to any individual or institution to use, copy, or
- X; redistribute this software so long as all of the original files are included
- X; unmodified, that it is not sold for profit, and that this copyright notice
- X; is retained.
- X;
- X
- X; im_lm.asm by Jean-loup Gailly.
- X
- X;im_lm.asm, optimized version of longest_match() and lm_process() in im_lmat.c
- X; Must be assembled with masm -ml. To be used only with C small model or
- X; compact model. This file is only optional. If you don't have masm, use the
- X; C version (add -DNO_ASM to CFLAGS in makefile.dos and remove im_lm.obj
- X; from OBJI).
- X;
- X; Turbo C 2.0 does not support static allocation of far data in
- X; the small model. So TC 2.0 users must assemble this with:
- X; tasm -ml -DDYN_ALLOC im_lm;
- X; OS/2 users must assemble this with -DOS2 -ml. To simplify the code,
- X; the option -DDYN_ALLOC is not supported for OS/2.
- X name im_lm
- X
- ifndef DYN_ALLOC
- X extrn _prev : word
- X extrn _next : word
- X prev equ _prev
- X next equ _next
- load_es_prev macro
- X mov cx,seg _prev
- X mov es,cx
- endm
- load_ds_next macro
- X mov si,seg _next
- X mov ds,si
- endm
- endif
- X
- X_BSS segment word public 'BSS'
- X extrn _window : byte
- X extrn _match_length : word
- X extrn _start_length : word
- X extrn _strstart : word
- X extrn _strsize : word
- X extrn _ins_h : word
- X extrn _h_shift : byte
- X extrn _checkpoint : word
- X extrn _bufsize : word
- X extrn _max_chain_length : word
- X extrn _min_match_length : word
- ifdef DYN_ALLOC
- X extrn _prev : word
- X extrn _next : word
- X prev equ 0 ; offset normalized to zero (except for OS/2)
- X next equ 0 ; offset normalized to zero (except for OS/2)
- load_es_prev macro
- X mov es,_prev[2] ; warning: the offset should be added under OS/2
- endm
- load_ds_next macro
- X mov ds,_next[2] ; warning: the offset should be added under OS/2
- endm
- endif
- X cur_best dw 1 dup(?) ; best match within longest_match
- X_BSS ends
- X
- DGROUP group _BSS
- X
- X_TEXT segment word public 'CODE'
- X assume cs: _TEXT, ds: DGROUP, ss: DGROUP
- X
- X extrn _write_match : near
- X
- X BSZ equ 4096 ; keep consistent with tailor.h
- X WSIZE equ 8192 ; keep consistent with im_lmat.c
- X NIL equ (WSIZE+BSZ)
- X MAX_DIST equ NIL
- X MAX_LENGTH equ 320 ; keep consistent with im_lmat.c
- X HASH_MASK equ 16383 ; (1<<14)-1
- X
- X; Process a block of characters already inserted in the window
- X; IN assertion: count > 0
- X public _lm_process
- X_lm_process proc near
- X push bp
- X mov bp,sp
- X push di
- X push si
- X
- X count equ word ptr [bp+4]
- X; delete_point equ ax
- X; ins_h equ bx
- X; h_shift equ cl
- X; count equ dx
- X; cur_match equ si
- X; strstart equ di
- X; min_match_length equ bp
- X
- X mov dx,count
- X mov bx,_ins_h
- X mov di,_strstart
- X lea ax,[di+MAX_LENGTH-1]
- X sub ax,_bufsize
- X jae del_ok
- X add ax,MAX_DIST
- del_ok: shl ax,1 ;delete_point as word index
- X load_es_prev
- X mov cl,_h_shift
- X load_ds_next
- X assume ds: nothing
- X jmp short insert
- X
- start_overflow:
- X sub di,di ;strstart = 0
- X sub ss:_checkpoint,MAX_DIST
- X jmp short check_count
- del_overflow:
- X mov ax,-2 ;delete_point = 0
- main_loop:
- X add ax,2 ;delete_point++ (word index)
- X cmp ax,2*MAX_DIST
- X je del_overflow
- X xchg ax,si ;si=2*delete_point
- X mov bp,next[si]
- X shl bp,1
- X mov es:prev[bp],NIL
- X xchg ax,si ;ax=2*delete_point
- X
- X inc di ;strstart++
- X cmp di,MAX_DIST
- X je start_overflow
- check_count:
- X dec dx ;count--
- X jz end_proc_ok
- insert:
- X shl bx,cl ;ins_h <<= h_shift
- X mov bp,ss:_min_match_length
- X xor bl,_window[di+bp-1] ;ins_h ^= window[s+min_match_length-1]
- X and bx,HASH_MASK
- X add bx,MAX_DIST+1
- X shl bx,1 ;word index
- X mov si,es:prev[bx] ;cur_match = match_head[ins_h]
- X mov es:prev[bx],di ;prev[ins_h+MAX_DIST+1] = strstart
- X shr bx,1 ;bx = ins_h + MAX_DIST + 1
- X shl di,1 ;di = strstart as word index
- X mov next[di],bx
- X sub bx,MAX_DIST+1 ;bx = ins_h
- X mov es:prev[di],si ;prev[s] = cur_match
- X shr di,1 ;di = strstart
- X shl si,1
- X mov next[si],di ;next[cur_match] = strstart
- X cmp di,ss:_checkpoint
- X jne main_loop
- X
- X push ax
- X push bx
- X push dx
- X mov ax,ss
- X mov ds,ax
- X assume ds: DGROUP
- X mov _match_length,0
- X mov _strstart,di
- X shr si,1 ;si = cur_match
- X cmp si,NIL ;cur_match == NIL ?
- X je call_write
- X call _longest_match ;returns best_match in si
- call_write:
- X push _match_length
- X push si ;best_match or NIL
- X call _write_match
- X add sp,4
- X pop dx
- X pop bx
- X or al,al
- X jnz failure
- X pop ax
- X load_es_prev
- X mov cl,_h_shift
- X load_ds_next
- X assume ds: nothing
- X jmp main_loop
- end_proc_ok:
- X mov ax,ss
- X mov ds,ax
- X assume ds: DGROUP
- X sub ax,ax
- X mov _strstart,di
- end_proc:
- X mov _ins_h,bx
- X pop si
- X pop di
- X pop bp
- X ret
- failure:
- X add sp,2 ;skip pushed ax
- X jmp short end_proc
- X
- X_lm_process endp
- X
- X; Find the longest match starting at the given string. Return its position
- X; and set its length in match_length. Matches shorter or equal to
- X; start_length are discarded, in which case match_length is unchanged
- X; and the result position is NIL.
- X; IN assertions: cur_match is the head of the hash chain for the current
- X; string (strstart) and is not NIL, start_length >= 1.
- X; registers: es points to the base of the prev array (preserved)
- X; si = cur_match and return value
- X; di = strstart
- X
- X; IPos longest_match(cur_match)
- X
- X public _longest_match
- X_longest_match proc near
- X
- X push bp
- X push di
- X
- X; match equ si
- X; scan equ di
- X; chain_count equ bp
- X; ma_length equ bx
- X
- X lea di,_window[di+2] ; di = window + strstart + 2
- X mov cur_best,NIL
- X mov bp,_max_chain_length ; chain_count = max_chain_length
- X mov bx,_start_length ; ma_length = start_length
- X mov ax,[bx+di-3] ; ax = scan[ma_length-1..ma_length]
- X mov cx,[di-2] ; cx = scan[0..1]
- X jmp short do_scan
- X
- X even ; align destination of branch
- long_loop:
- X; at this point, di == scan+2, si = cur_match
- X mov ax,[bx+di-3] ; ax = scan[ma_length-1..ma_length]
- X mov cx,[di-2] ; cx = scan[0..1]
- short_loop:
- X dec bp ; --chain_count
- X jz the_end
- X; at this point, di == scan+2, si = cur_match,
- X; ax = scan[ma_length-1..ma_length] and cx = scan[0..1]
- X shl si,1 ; cur_match as word index
- X mov si,es:prev[si] ; cur_match = prev[cur_match]
- X cmp si,NIL
- X je the_end
- do_scan:
- X cmp ax,word ptr _window[bx+si-1] ; check match at ma_length-1
- X jne short_loop
- X cmp cx,word ptr _window[si] ; check min_match_length match
- X jne short_loop
- X mov dx,si ; dx = cur_match
- X lea si,_window[si+2] ; si = match
- X mov ax,di ; ax = scan+2
- X mov cx,ds
- X mov es,cx
- X mov cx,(MAX_LENGTH-2)/2 ; scan for at most MAX_LENGTH bytes
- X repe cmpsw ; loop until mismatch
- X load_es_prev ; reset es to address the prev array
- X mov cl,[di-2] ; mismatch on first or second byte?
- X sub cl,[si-2] ; dl = 0 if first bytes equal
- X xchg ax,di ; di = scan+2, ax = end of scan
- X sub ax,di ; ax = len
- X sub cl,1 ; set carry if cl == 0 (can't use DEC)
- X adc ax,0 ; ax = carry ? len+1 : len
- X mov si,dx ; si = cur_match
- X cmp ax,bx ; len > ma_length ?
- X jle long_loop
- X mov cur_best,si ; cur_best = cur_match
- X mov bx,ax ; bx = ma_length = len
- X cmp ax,_strsize ; len >= strsize ?
- X jle long_loop
- the_end:
- X cmp bx,_start_length ; ma_length > start_length ?
- X jle return
- X mov _match_length,bx ; match_length = ma_length
- return:
- X mov si,cur_best ; result = cur_best
- X pop di
- X pop bp
- X ret
- X
- X_longest_match endp
- X
- X_TEXT ends
- end
- END_OF_FILE
- if test 9944 -ne `wc -c <'im_lm.asm'`; then
- echo shar: \"'im_lm.asm'\" unpacked with wrong size!
- fi
- # end of 'im_lm.asm'
- fi
- if test -f 'implode.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'implode.c'\"
- else
- echo shar: Extracting \"'implode.c'\" \(8838 characters\)
- sed "s/^X//" >'implode.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * implode.c by Richard B. Wales.
- X *
- X * PURPOSE
- X *
- X * Compress an input file using the ZIP "implosion" method.
- X *
- X * DISCUSSION
- X *
- X * The "implosion" algorithm is a composite of (1) OPM/L compres-
- X * sion within a sliding window, and (2) variable-length binary
- X * encoding of various parts of the OPM/L output.
- X *
- X * For a detailed treatment of OPM/L compression, see the source
- X * file "im_lmat.c".
- X *
- X * For a detailed treatment of variable-length binary encoding,
- X * see the source file "im_ctree.c".
- X *
- X * Since Pass Two (binary encoding) depends on a statistical anal-
- X * ysis of the entire output of Pass One (OPM/L compression), the
- X * Pass One output is saved in a temporary file and re-read for
- X * Pass Two. Implosion is thus a two-pass algorithm.
- X *
- X * An outline of the algorithm follows:
- X *
- X * (1) The entire input file is read and compressed via the OPM/L
- X * technique. The OPM/L output is saved in a temporary file.
- X *
- X * (2) The compressed info from (1) is analyzed, and various fre-
- X * quency counts are tallied.
- X *
- X * (3) Based on the frequency counts, a decision is made as to
- X * whether or not the "literal" characters (those not matched
- X * in earlier parts of the input) should be represented via a
- X * binary code tree or left "as is". If there are not very
- X * many literal characters, or if their frequency distribution
- X * is fairly even, the number of bits saved through coding may
- X * be exceeded by the amount of info which must be included to
- X * describe the tree.
- X *
- X * (4) The temporary file from (1) is re-read. The information is
- X * further compressed via the binary code trees, and the result
- X * is sent to the ZIP output file.
- X *
- X * REFERENCES
- X *
- X * APPNOTE.TXT documentation file in PKZIP 1.10 distribution.
- X *
- X * See also references in the "im_lmat.c" and "im_ctree.c" source
- X * files.
- X *
- X * INTERFACE
- X *
- X * int imp_setup (long filesize, int pack_level)
- X * Initialize the "implode" routines for a new file.
- X *
- X * int imp_p1 (char *buf, int count)
- X * Process "count" input characters pointed to by "buf". This
- X * routine is called as many times as needed to process the
- X * entire input file. There is no upper limit on "count".
- X *
- X * int imp_size (long *size, char *opts)
- X * Terminate processing of the input file, and return the com-
- X * pressed size ("size") and implosion option flags ("opts").
- X *
- X * int imp_p2 (FILE *outfp)
- X * Output the entire compressed file -- including S-F trees and
- X * data -- to the ZIP output file "outfp".
- X *
- X * int imp_clear (void)
- X * Clean up after processing and outputting a file. This rou-
- X * tine may be called at any time to abort further processing.
- X *
- X * All the above routines return zero if successful, or a non-zero
- X * value if there was an error.
- X */
- X
- X#include "implode.h"
- X#include "ziperr.h"
- X
- X
- X/***********************************************************************
- X *
- X * Error return codes for the main ZIP program.
- X * Most of these are in "ziperr.h".
- X */
- X
- X#define ZE_MAP(err) \
- X ( ((err) == IM_OK) ? ZE_OK \
- X : ((err) == IM_NOMEM) ? ZE_MEM \
- X : ((err) == IM_IOERR) ? ZE_TEMP \
- X : (fprintf(stderr,"\nZE_MAP(%d)",(err)), \
- X ZE_LOGIC))
- X
- X
- X/***********************************************************************
- X *
- X * State variable for the implosion routines.
- X */
- X
- X#define IMP_SETUP 0 /* need to do "imp_setup" */
- X#define IMP_P1 1 /* setup done, ready for Pass 1 */
- X#define IMP_P2 2 /* Pass 1 done, ready for Pass 2 */
- X#define IMP_CLEAR 3 /* Pass 2 done, ready for "imp_clear" */
- X
- local int imp_state = IMP_SETUP;
- X
- X
- X/***********************************************************************
- X *
- X * Global variables.
- X */
- X
- XFDATA fd;
- X
- X
- X/***********************************************************************
- X *
- X * Set up for performing implosion on a new file.
- X */
- X
- int
- imp_setup (filesize, pack_level)
- X long filesize; /* input file size */
- X int pack_level; /* 0 = best speed, 9 = best compression, other = default */
- X{
- X ImpErr retcode;
- X extern char *tempname();
- X
- X if (imp_state != IMP_SETUP)
- X { fprintf (stderr, "\nimp_setup called with wrong state %d",
- X imp_state);
- X return ZE_LOGIC;
- X }
- X imp_state = IMP_P1;
- X
- X /* Set up the initial parameters. Use an 8K window if the input
- X * file is greater than or equal to 5.5K, a 4K window otherwise.
- X */
- X fd.fd_bufsize = 8192;
- X if (filesize < 5632) fd.fd_bufsize = 4096;
- X
- X fd.fd_strsize = 320;
- X fd.fd_nbits = (fd.fd_bufsize == 4096) ? 6 : 7;
- X
- X /* Create a temporary file for the Pass One output. */
- X fd.fd_temp = topen ('I');
- X if (fd.fd_temp == NULL)
- X return ZE_MEM;
- X
- X /*
- X * Initialize the "longest match" routines.
- X * "ct_init" is called at this point because the "lm_input" routine
- X * (called in "imp_p1") calls the "ct_tally" routine.
- X */
- X retcode = lm_init (pack_level);
- X if (retcode != IM_OK) return ZE_MAP (retcode);
- X retcode = ct_init ();
- X return ZE_MAP (retcode);
- X}
- X
- X
- X/***********************************************************************
- X *
- X * Feed characters to the implosion computation.
- X * This routine is called as many times as needed, until the entire
- X * input file has been processed.
- X */
- X
- int
- imp_p1 (buf, count)
- X char *buf; /* input characters */
- X int count; /* character count */
- X{ ImpErr retcode;
- X
- X if (imp_state != IMP_P1)
- X { fprintf (stderr, "\nimp_p1 called with wrong state %d",
- X imp_state);
- X return ZE_LOGIC;
- X }
- X
- X if (buf == NULL || count < 0)
- X { fprintf (stderr, "\nimp_p1 called with bad arguments");
- X return ZE_LOGIC;
- X }
- X retcode = lm_input ((U_CHAR *) buf, (U_INT) count);
- X return ZE_MAP (retcode);
- X}
- X
- X
- X/***********************************************************************
- X *
- X * Terminate processing of input for this file, and determine the size
- X * this file will have if it is imploded. Also, find out whether two
- X * or three S-F trees will be used (needed for directory entries).
- X */
- X
- int
- imp_size (size, opts)
- X long *size; /* imploded size */
- X char *opts; /* implosion option info */
- X{ ImpErr retcode;
- X
- X if (imp_state != IMP_P1)
- X { fprintf (stderr, "\nimp_size called with wrong state %d",
- X imp_state);
- X return ZE_LOGIC;
- X }
- X imp_state = IMP_P2;
- X
- X if (size == NULL || opts == NULL)
- X { fprintf (stderr, "\nimp_size called with bad arguments");
- X return ZE_LOGIC;
- X }
- X retcode = lm_windup ();
- X if (retcode != IM_OK) return ZE_MAP (retcode);
- X retcode = ct_mktrees ();
- X if (retcode != IM_OK) return ZE_MAP (retcode);
- X *size = fd.fd_clen;
- X *opts = (char)(((fd.fd_bufsize == 8192) ? 0x02 : 0)
- X | ((fd.fd_method == LITERAL_TREE) ? 0x04 : 0));
- X return ZE_OK;
- X}
- X
- X
- X/***********************************************************************
- X *
- X * Output the imploded version of the file (but not the file directory
- X * info) to the ZIP file.
- X */
- X
- int
- imp_p2 (outfp)
- X FILE *outfp; /* output (ZIP) file */
- X{ ImpErr retcode;
- X
- X if (imp_state != IMP_P2)
- X { fprintf (stderr, "\nimp_p2 called with wrong state %d",
- X imp_state);
- X return ZE_LOGIC;
- X }
- X imp_state = IMP_CLEAR;
- X
- X if (outfp == NULL)
- X { fprintf (stderr, "\nimp_p2 called with bad arguments");
- X return ZE_LOGIC;
- X }
- X retcode = ct_wrtrees (outfp);
- X if (retcode != IM_OK) return ZE_MAP (retcode);
- X retcode = ct_wrdata (outfp);
- X if (retcode != IM_OK) return ZE_MAP (retcode);
- X fflush (outfp);
- X if (ferror (outfp)) return ZE_TEMP;
- X return ZE_OK;
- X}
- X
- X
- X/***********************************************************************
- X *
- X * Clean up after doing an implosion.
- X * This routine may also be called at any time to abort an implosion.
- X */
- X
- int
- imp_clear ()
- X{ (void) lm_windup ();
- X if (fd.fd_temp != NULL)
- X (void) tclose (fd.fd_temp);
- X (void) ct_windup ();
- X imp_state = IMP_SETUP;
- X return ZE_OK;
- X}
- X
- X
- X/**********************************************************************/
- END_OF_FILE
- if test 8838 -ne `wc -c <'implode.c'`; then
- echo shar: \"'implode.c'\" unpacked with wrong size!
- fi
- # end of 'implode.c'
- fi
- if test -f 'shrink.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'shrink.c'\"
- else
- echo shar: Extracting \"'shrink.c'\" \(10431 characters\)
- sed "s/^X//" >'shrink.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * shrink.c by Mark Adler.
- X */
- X
- X#include "zip.h"
- X#include "tempf.h"
- X
- X
- X/*
- X Shrink.Pas version 1.2 by R. P. Byrne, 1989 (in Pascal and assembler).
- X We here heartily acknowledge R. P. Byrne's contribution to this project.
- X The existence of this program really triggered our efforts to write a
- X portable Unix zip. What little remains of Byrne's program lies in this
- X source file, and those remnants are mostly in the variable and routine
- X names, since it has been translated and extensively modified and rewritten.
- X
- X Stolen, translated into C, and modified by Mark Adler, 11 October 1990.
- X Severely modified again by Mark Adler, 11 July 1991, to remove the
- X unnecessary FreeList and ClearTable arrays, and to replace the recursive
- X Prune() routine with a non-recursive method.
- X As Stravinsky once said: "Mediocre composers plagiarize.
- X Great composers steal."
- X*/
- X
- X/* Compress a set of input files into a Zip file using Lempel-Ziv-Welch */
- X/* (LZW) compression techniques (the "shrink" method). */
- X
- X
- X#define MINBITS 9 /* Starting code size of 9 bits */
- X#define MAXBITS 13 /* Maximum code size of 13 bits */
- X#define TABLESIZE 8191 /* We'll need 4K entries in table */
- X#define SPECIAL 256 /* Special function code */
- X#define INCSIZE 1 /* Code for a jump in code size */
- X#define CLEARCODE 2 /* Code for code table has been cleared */
- X#define FIRSTENTRY 257 /* First available table entry */
- X
- X
- X/* Define data types needed to implement a code table for LZW compression */
- X
- typedef struct CodeRec {
- X /* Code Table record format... */
- X short Child; /* Addr of 1st suffix for this prefix */
- X short Sibling; /* Addr of next suffix in chain */
- X uch Suffix; /* Suffix character */
- X} CodeRec;
- X
- typedef CodeRec CodeArray[TABLESIZE + 1]; /* Define the code table */
- X
- X
- X
- X/* Private globals */
- local CodeRec far *CodeTable; /* Points to code table for LZW compression */
- X
- local int NextFree; /* Next free table entry */
- X
- local int CodeSize; /* Size of codes (in bits) currently being written */
- local int MaxCode; /* Largest code that can be written in CodeSize bits */
- X
- local int FirstCh; /* Flag indicating the START of a shrink operation */
- X
- local tFILE *tempf = NULL; /* Temporary file */
- local ulg count; /* Count of bytes written */
- X
- X
- X/* Local functions */
- X#ifdef PROTO
- X local void PutCode(int);
- X local int Build_Data_Structures(void);
- X local void Destroy_Data_Structures(void);
- X local void Initialize_Data_Structures(void);
- X local void Clear_Table(void);
- X local void Table_Add(int, int);
- X#endif /* PROTO */
- X
- X
- X/* Macro for PutCode() that writes to tempf and counts bytes in count */
- X#define PUT(c) {tputc(c, tempf); count++;}
- X
- local void PutCode(c)
- int c; /* code to send */
- X/* Write out the low CodeSize bits of c using the PUT macro. If c is -1,
- X then flush the bit buffer. Assumes CodeSize < 16. By Mark Adler. */
- X{
- X static int b = 0; /* current bits waiting to go out */
- X static int n = 0; /* number of bits in b */
- X /* masks for all bit values */
- X static int x[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff,
- X 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
- X
- X if (c == -1)
- X {
- X if (n)
- X {
- X if (n > 8)
- X {
- X PUT((char)b)
- X PUT((char)((b >> 8) & x[n - 8]))
- X }
- X else
- X PUT((char)(b & x[n]))
- X b = n = 0;
- X }
- X }
- X else
- X {
- X b |= (c & x[CodeSize]) << n;
- X n += CodeSize;
- X if (n >= 16)
- X {
- X PUT((char)b)
- X PUT((char)(b >> 8))
- X if (n == 16)
- X b = n = 0;
- X else
- X {
- X n -= 16;
- X b = (c >> (CodeSize - n)) & x[n];
- X }
- X }
- X }
- X}
- X
- X
- X
- local int Build_Data_Structures()
- X/* Allocate tables for shrinking. Return true on failure. */
- X{
- X return (CodeTable = (CodeRec far *)farmalloc(sizeof(CodeArray))) == NULL;
- X}
- X
- X
- X
- local void Destroy_Data_Structures()
- X/* Deallocate tables for shrinking. */
- X{
- X if (CodeTable != NULL)
- X {
- X farfree((voidp far *)CodeTable);
- X CodeTable = NULL;
- X }
- X}
- X
- X
- X
- local void Initialize_Data_Structures()
- X/* Clear tables for shrinking. */
- X{
- X int i; /* counter for table entries */
- X CodeRec far *t; /* pointer to current table entry */
- X
- X /* Initialize parent symbols */
- X for (i = 0, t = CodeTable; i <= 255; i++, t++)
- X {
- X t->Child = -1;
- X t->Suffix = (uch)i;
- X }
- X
- X /* Build free list */
- X NextFree = FIRSTENTRY;
- X for (i = FIRSTENTRY, t = CodeTable + FIRSTENTRY; i < TABLESIZE; i++, t++)
- X t->Child = i + 1;
- X t->Child = -1;
- X}
- X
- X
- X
- local void Clear_Table()
- X/* Clear the leaves of the tree--assume all entries used (NextFree == -1) */
- X{
- X int n; /* node counter */
- X CodeRec far *p; /* pointer to next node to look at */
- X short far *q; /* pointer to node child or sibling entry */
- X
- X /* Mark leaf nodes */
- X p = CodeTable + TABLESIZE;
- X n = TABLESIZE + 1 - FIRSTENTRY;
- X do {
- X if (p->Child == -1)
- X p->Child = -2;
- X p--;
- X } while (--n);
- X
- X /* Shake leaves from tree */
- X p = CodeTable;
- X n = 256;
- X do {
- X q = &p->Child;
- X while (*q != -1 && CodeTable[*q].Child == -2)
- X *q = CodeTable[*q].Sibling;
- X p++;
- X } while (--n);
- X p = CodeTable + FIRSTENTRY;
- X n = TABLESIZE + 1 - FIRSTENTRY;
- X do {
- X if (p->Child != -2)
- X {
- X q = &p->Child;
- X while (*q != -1 && CodeTable[*q].Child == -2)
- X *q = CodeTable[*q].Sibling;
- X q = &p->Sibling;
- X while (*q != -1 && CodeTable[*q].Child == -2)
- X *q = CodeTable[*q].Sibling;
- X }
- X p++;
- X } while (--n);
- X
- X /* Build the list of free table entries */
- X NextFree = -1;
- X p = CodeTable + TABLESIZE;
- X n = TABLESIZE + 1 - FIRSTENTRY;
- X do {
- X if (p->Child == -2)
- X {
- X p->Child = NextFree;
- X NextFree = n + FIRSTENTRY - 1;
- X }
- X p--;
- X } while (--n);
- X}
- X
- X
- X
- local void Table_Add(p, s)
- int p; /* prefix to add to */
- int s; /* suffix to add to it */
- X/* Add an entry to the table. */
- X{
- X int f; /* next free node */
- X
- X if ((f = NextFree) != -1)
- X {
- X NextFree = CodeTable[f].Child;
- X CodeTable[f].Child = -1;
- X CodeTable[f].Sibling = -1;
- X CodeTable[f].Suffix = (uch)s;
- X if (CodeTable[p].Child == -1)
- X CodeTable[p].Child = f;
- X else
- X {
- X p = CodeTable[p].Child;
- X while (CodeTable[p].Sibling != -1)
- X p = CodeTable[p].Sibling;
- X CodeTable[p].Sibling = f;
- X }
- X }
- X}
- X
- X
- local int lastcode;
- X
- int shr_setup()
- X/* Initialize shrink() routines. Return an error code in the ZE_ class. */
- X{
- X if (Build_Data_Structures())
- X return ZE_MEM;
- X Initialize_Data_Structures();
- X FirstCh = 1;
- X lastcode = -1;
- X if ((tempf = topen('S')) == NULL)
- X return ZE_MEM;
- X count = 0;
- X return ZE_OK;
- X}
- X
- X
- int shr_p1(b, n)
- uch *b; /* buffer with bytes to shrink */
- extent n; /* number of bytes in buffer */
- X/* Shrink n bytes at *b. Return an error code in the ZE_ class. */
- X{
- X int f; /* result of Table_Lookup */
- X int s; /* byte to shrink */
- X
- X if (FirstCh && n)
- X { /* If just getting started ... */
- X CodeSize = MINBITS; /* Initialize code size to minimum */
- X MaxCode = (1 << CodeSize) - 1;
- X lastcode = *b++; n--; /* get first character from input, */
- X FirstCh = 0; /* and reset the first char flag. */
- X }
- X while (NextFree == -1 && n)
- X {
- X /* Ok, lets clear the code table (adaptive reset) */
- X PutCode(lastcode);
- X PutCode(SPECIAL);
- X PutCode(CLEARCODE);
- X Clear_Table();
- X Table_Add(lastcode, s = *b++); n--;
- X lastcode = s;
- X }
- X while (n)
- X {
- X s = *b++; n--;
- X f = CodeTable[lastcode].Child;
- X while (f != -1 && CodeTable[f].Suffix != (uch)s)
- X f = CodeTable[f].Sibling;
- X if (f != -1)
- X /* If lastcode:s pair is found in the code table, then ... */
- X /* ... set lastcode to the entry where the pair is located */
- X lastcode = f;
- X else
- X {
- X /* Not in table */
- X PutCode(lastcode); /* Write current lastcode */
- X Table_Add(lastcode, s); /* Attempt to add to code table */
- X lastcode = s; /* Reset lastcode for new char */
- X if (NextFree > MaxCode && CodeSize < MAXBITS)
- X {
- X /* Time to increase the code size and change the max. code */
- X PutCode(SPECIAL);
- X PutCode(INCSIZE);
- X CodeSize++;
- X MaxCode = (1 << CodeSize) - 1;
- X }
- X while (NextFree == -1 && n)
- X {
- X /* Ok, lets clear the code table (adaptive reset) */
- X PutCode(lastcode);
- X PutCode(SPECIAL);
- X PutCode(CLEARCODE);
- X Clear_Table();
- X Table_Add(lastcode, s = *b++); n--;
- X lastcode = s;
- X }
- X }
- X }
- X return ZE_OK;
- X}
- X
- X
- int shr_size(s)
- ulg *s; /* return value: size of shrunk data */
- X/* End shrink and return size of shrunk data in *s. Return an error code in
- X the ZE_ class. */
- X{
- X PutCode(lastcode); /* Write last prefix code */
- X PutCode(-1); /* Tell putcode to flush remaining bits */
- X Destroy_Data_Structures();
- X *s = count;
- X return tflush(tempf) || terror(tempf) ? ZE_TEMP : ZE_OK;
- X}
- X
- X
- int shr_p2(f)
- XFILE *f; /* file to write shrunk data to */
- X/* Copy shrunk data from temporary file to zip file *f. Return an error
- X code in the ZE_ class. */
- X{
- X char *b; /* malloc'ed buffer for copying */
- X extent k; /* holds result of fread */
- X
- X if ((b = malloc(BSZ)) == NULL)
- X return ZE_MEM;
- X trewind(tempf);
- X while ((k = tread(b, 1, BSZ, tempf)) > 0)
- X if (zfwrite(b, 1, k, f) != k)
- X {
- X free((voidp *)b);
- X return ZE_TEMP;
- X }
- X free((voidp *)b);
- X if (terror(tempf))
- X return ZE_TEMP;
- X tclose(tempf);
- X tempf = NULL;
- X return ZE_OK;
- X}
- X
- X
- int shr_clear()
- X/* Terminate shrink procedure (at any time). Return an error code in
- X the ZE_ class (always ZE_OK). */
- X{
- X Destroy_Data_Structures();
- X if (tempf != NULL)
- X {
- X tclose(tempf);
- X tempf = NULL;
- X }
- X return ZE_OK;
- X}
- END_OF_FILE
- if test 10431 -ne `wc -c <'shrink.c'`; then
- echo shar: \"'shrink.c'\" unpacked with wrong size!
- fi
- # end of 'shrink.c'
- fi
- if test -f 'util.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'util.c'\"
- else
- echo shar: Extracting \"'util.c'\" \(10800 characters\)
- sed "s/^X//" >'util.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * util.c by Mark Adler.
- X */
- X
- X#include "zip.h"
- X
- X/* Local functions */
- X#ifdef PROTO
- X local int recmatch(char *, char *);
- X#endif /* PROTO */
- X
- X
- char *isshexp(p)
- char *p; /* candidate sh expression */
- X/* If p is a sh expression, a pointer to the first special character is
- X returned. Otherwise, NULL is returned. */
- X{
- X int c;
- X
- X c = -1;
- X for (; *p; p++)
- X#ifdef VMS
- X if (c != '\\' && (*p == '%' || *p == '*'))
- X#else /* !VMS */
- X if (c != '\\' && (*p == '?' || *p == '*' || *p == '['))
- X#endif /* ?VMS */
- X return p;
- X return NULL;
- X}
- X
- X
- local int recmatch(p, s)
- char *p; /* sh pattern to match */
- char *s; /* string to match it to */
- X/* Recursively compare the sh pattern p with the string s and return 1 if
- X they match, and 0 or 2 if they don't or if there is a syntax error in the
- X pattern. This routine recurses on itself no deeper than the number of
- X characters in the pattern. */
- X{
- X int c; /* pattern char or start of range in [-] loop */
- X
- X /* Get first character, the pattern for new recmatch calls follows */
- X c = *p++;
- X
- X /* If that was the end of the pattern, match if string empty too */
- X if (c == 0)
- X return *s == 0;
- X
- X /* '?' (or '%') matches any character (but not an empty string) */
- X#ifdef VMS
- X if (c == '%')
- X#else /* !VMS */
- X if (c == '?')
- X#endif /* ?VMS */
- X return *s ? recmatch(p, s + 1) : 0;
- X
- X /* '*' matches any number of characters, including zero */
- X if (c == '*')
- X {
- X if (*p == 0)
- X return 1;
- X for (; *s; s++)
- X if ((c = recmatch(p, s)) != 0)
- X return c;
- X return 2; /* 2 means give up--shmatch will return false */
- X }
- X
- X#ifndef VMS /* No bracket matching in VMS */
- X /* Parse and process the list of characters and ranges in brackets */
- X if (c == '[')
- X {
- X int e; /* flag true if next char to be taken literally */
- X char *q; /* pointer to end of [-] group */
- X int r; /* flag true to match anything but the range */
- X
- X if (*s == 0) /* need a character to match */
- X return 0;
- X p += (r = *p == '!'); /* see if reverse */
- X for (q = p, e = 0; *q; q++) /* find closing bracket */
- X if (e)
- X e = 0;
- X else
- X if (*q == '\\')
- X e = 1;
- X else if (*q == ']')
- X break;
- X if (*q != ']') /* nothing matches if bad syntax */
- X return 0;
- X for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */
- X {
- X if (e == 0 && *p == '\\') /* set escape flag if \ */
- X e = 1;
- X else if (e == 0 && *p == '-') /* set start of range if - */
- X c = *(p-1);
- X else
- X {
- X if (*(p+1) != '-')
- X for (c = c ? c : *p; c <= *p; c++) /* compare range */
- X#ifdef OS2
- X if (tolower(c) == tolower(*s))
- X#else /* !OS2 */
- X if (c == *s)
- X#endif /* ?OS2 */
- X return r ? 0 : recmatch(q + 1, s + 1);
- X c = e = 0; /* clear range, escape flags */
- X }
- X }
- X return r ? recmatch(q + 1, s + 1) : 0; /* bracket match failed */
- X }
- X#endif /* !VMS */
- X
- X /* If escape ('\'), just compare next character */
- X if (c == '\\')
- X if ((c = *p++) == 0) /* if \ at end, then syntax error */
- X return 0;
- X
- X /* Just a character--compare it */
- X#ifdef OS2
- X return tolower(c) == tolower(*s) ? recmatch(p, ++s) : 0;
- X#else /* !OS2 */
- X return c == *s++ ? recmatch(p, s) : 0; /* compare one character */
- X#endif /* ?OS2 */
- X}
- X
- X
- int shmatch(p, s)
- char *p; /* sh pattern to match */
- char *s; /* string to match it to */
- X/* Compare the sh pattern p with the string s and return true if they match,
- X false if they don't or if there is a syntax error in the pattern. */
- X{
- X return recmatch(p, s) == 1;
- X}
- X
- X
- X#ifdef MSDOS
- X
- int dosmatch(p, s)
- char *p; /* dos pattern to match */
- char *s; /* string to match it to */
- X/* Break the pattern and string into name and extension parts and match
- X each separately using shmatch(). */
- X{
- X char *p1, *p2; /* pattern sections */
- X char *s1, *s2; /* string sections */
- X int r; /* result */
- X
- X if ((p1 = malloc(strlen(p) + 1)) == NULL ||
- X (s1 = malloc(strlen(s) + 1)) == NULL)
- X {
- X if (p1 != NULL)
- X free((voidp *)p1);
- X return 0;
- X }
- X strcpy(p1, p);
- X strcpy(s1, s);
- X if ((p2 = strrchr(p1, '.')) != NULL)
- X *p2++ = 0;
- X else
- X p2 = "";
- X if ((s2 = strrchr(s1, '.')) != NULL)
- X *s2++ = 0;
- X else
- X s2 = "";
- X r = shmatch(p2, s2) && shmatch(p1, s1);
- X free((voidp *)p1);
- X free((voidp *)s1);
- X return r;
- X}
- X
- X#endif /* MSDOS */
- X
- X
- voidp far **search(b, a, n, cmp)
- voidp *b; /* pointer to value to search for */
- voidp far **a; /* table of pointers to values, sorted */
- extent n; /* number of pointers in a[] */
- int (*cmp) OF((voidp *, voidp far *)); /* comparison function for search */
- X/* Search for b in the pointer list a[0..n-1] using the compare function
- X cmp(b, c) where c is an element of a[i] and cmp() returns negative if
- X *b < *c, zero if *b == *c, or positive if *b > *c. If *b is found,
- X search returns a pointer to the entry in a[], else search() returns
- X NULL. The nature and size of *b and *c (they can be different) are
- X left up to the cmp() function. A binary search is used, and it is
- X assumed that the list is sorted in ascending order. */
- X{
- X voidp far **i; /* pointer to midpoint of current range */
- X voidp far **l; /* pointer to lower end of current range */
- X int r; /* result of (*cmp)() call */
- X voidp far **u; /* pointer to upper end of current range */
- X
- X l = (voidp far **)a; u = l + (n-1);
- X while (u >= l)
- X if ((r = (*cmp)(b, *(i = l + ((u - l) >> 1)))) < 0)
- X u = i - 1;
- X else if (r > 0)
- X l = i + 1;
- X else
- X return (voidp far **)i;
- X return NULL; /* If b were in list, it would belong at l */
- X}
- X
- X
- X
- X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
- local ulg crctab[] = {
- X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- X 0x2d02ef8dL
- X};
- X
- X
- ulg crc32(c, b)
- ulg c; /* current contents of crc shift register */
- int b; /* byte (eight bits) to run through */
- X/* Return the CRC-32 c updated with the eight bits in b. */
- X{
- X return crctab[((int)c ^ b) & 0xff] ^ (c >> 8);
- X}
- X
- X
- ulg updcrc(s, n)
- char *s; /* pointer to bytes to pump through */
- extent n; /* number of bytes in s[] */
- X/* Run a set of bytes through the crc shift register. If s is a NULL
- X pointer, then initialize the crc shift register contents instead.
- X Return the current crc in either case. */
- X{
- X register ulg c; /* temporary variable */
- X
- X static ulg crc = 0xffffffffL; /* shift register contents */
- X
- X if (s == NULL)
- X c = 0xffffffffL;
- X else
- X {
- X c = crc;
- X while (n--)
- X c = crctab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
- X }
- X crc = c;
- X return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
- X}
- END_OF_FILE
- if test 10800 -ne `wc -c <'util.c'`; then
- echo shar: \"'util.c'\" unpacked with wrong size!
- fi
- # end of 'util.c'
- fi
- if test -f 'zip.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zip.h'\"
- else
- echo shar: Extracting \"'zip.h'\" \(8017 characters\)
- sed "s/^X//" >'zip.h' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * zip.h by Mark Adler.
- X */
- X
- X
- X/* Set up portability */
- X#include "tailor.h"
- X
- X/* Define malloc() and string functions */
- X#ifdef MODERN
- X# include <string.h>
- X#else /* !MODERN */
- X voidp *malloc();
- X char *getenv();
- X long atol();
- X char *strcpy();
- X char *strcat();
- X char *strchr();
- X char *strrchr();
- X# ifndef ZMEM
- X char *memset();
- X char *memcpy();
- X# endif /* !ZMEM */
- X#endif /* ?MODERN */
- X
- X
- X/* Define fseek() commands */
- X#ifndef SEEK_SET
- X# define SEEK_SET 0
- X#endif /* !SEEK_SET */
- X
- X#ifndef SEEK_CUR
- X# define SEEK_CUR 1
- X#endif /* !SEEK_CUR */
- X
- X
- X/* Forget FILENAME_MAX (incorrectly = 14 on some System V) */
- X#ifdef MSDOS
- X# define FNMAX 256
- X#else /* !MSDOS */
- X# define FNMAX 1024
- X#endif /* ?MSDOS */
- X
- X
- X/* Types centralized here for easy modification */
- X#define local static /* More meaningful outside functions */
- typedef unsigned char uch; /* unsigned 8-bit value */
- typedef unsigned short ush; /* unsigned 16-bit value */
- typedef unsigned long ulg; /* unsigned 32-bit value */
- X
- X
- X/* Lengths of headers after signatures in bytes */
- X#define LOCHEAD 26
- X#define CENHEAD 42
- X#define ENDHEAD 18
- X
- X
- X/* Structures for in-memory file information */
- struct zlist {
- X /* See central header in zipfile.c for what vem..off are */
- X ush vem, ver, flg, how;
- X ulg tim, crc, siz, len;
- X extent nam, ext, cext, com; /* offset of ext must be >= LOCHEAD */
- X ush dsk, att, lflg; /* offset of lflg must be >= LOCHEAD */
- X ulg atx, off;
- X char *name; /* File name in zip file */
- X char *extra; /* Extra field (set only if ext != 0) */
- X char *cextra; /* Extra in central (set only if cext != 0) */
- X char *comment; /* Comment (set only if com != 0) */
- X char *zname; /* Name for new zip file header */
- X int mark; /* Marker for files to operate on */
- X int trash; /* Marker for files to delete */
- X struct zlist far *nxt; /* Pointer to next header in list */
- X};
- struct flist {
- X char *name; /* Pointer to zero-delimited name */
- X char *zname; /* Name used for zip file headers */
- X struct flist far * far *lst; /* Pointer to link pointing here */
- X struct flist far *nxt; /* Link to next name */
- X};
- X
- X
- X/* Error return codes and PERR macro */
- X#include "ziperr.h"
- X
- X
- X/* Public globals */
- extern char errbuf[]; /* Handy place to build error messages */
- extern int recurse; /* Recurse into directories encountered */
- extern int pathput; /* Store path with name */
- X#define BEST -1 /* Use best method */
- X#define STORE 0 /* Store method */
- X#define SHRINK 1 /* Use shrink or store only */
- X#define IMPLODE 6 /* Use implode or store only */
- extern int method; /* Restriction on compression method */
- extern int dosify; /* Make new entries look like MSDOS */
- extern char *special; /* Don't compress special suffixes */
- extern int verbose; /* Report oddities in zip file structure */
- extern int level; /* Compression level */
- X#ifdef VMS
- X extern int vmsver; /* Append VMS version number to file names */
- X#endif /* VMS */
- extern int linkput; /* Store symbolic links as such */
- extern int noisy; /* False for quiet operation */
- extern char *key; /* Scramble password or NULL */
- extern char *tempath; /* Path for temporary files */
- extern char *zipfile; /* New or existing zip archive (zip file) */
- extern ulg zipbeg; /* Starting offset of zip structures */
- extern ulg cenbeg; /* Starting offset of central directory */
- extern struct zlist far *zfiles;/* Pointer to list of files in zip file */
- extern extent zcount; /* Number of files in zip file */
- extern extent zcomlen; /* Length of zip file comment */
- extern char *zcomment; /* Zip file comment (not zero-terminated) */
- extern struct zlist far **zsort;/* List of files sorted by name */
- extern struct flist far *found; /* List of names found */
- extern struct flist far * far *fnxt; /* Where to put next in found list */
- extern extent fcount; /* Count of names in found list */
- extern int shract; /* Shrink active */
- extern int impact; /* Implosion active */
- X
- X
- X/* Diagnostic function */
- X#ifdef DEBUG
- X# define diag(where) fprintf(stderr, "zip diagnostic: %s\n", where)
- X#else /* !DEBUG */
- X# define diag(where)
- X#endif /* ?DEBUG */
- X
- X
- X/* Public function prototypes */
- X
- X /* in zip.c, zipcloak.c, or zipsplit.c */
- void warn OF((char *, char *));
- X
- X /* in zipup.c */
- int zipcopy OF((struct zlist far *, FILE *, FILE *));
- X#ifndef UTIL
- X int percent OF((ulg, ulg));
- X int zipup OF((struct zlist far *, FILE *));
- X#endif /* !UTIL */
- X
- X /* in zipfile.c */
- X#ifndef UTIL
- X struct zlist far *zsearch OF((char *));
- X int trash OF((void));
- X#endif /* !UTIL */
- char *ziptyp OF((char *));
- int readzipfile OF((void));
- int putlocal OF((struct zlist far *, FILE *));
- int putcentral OF((struct zlist far *, FILE *));
- int putend OF((int, ulg, ulg, extent, char *, FILE *));
- X
- X /* in fileio.c */
- X#ifndef UTIL
- X# ifdef MSDOS
- X int wild OF((char *));
- X# endif /* MSDOS */
- X char *getnam OF((char *));
- X struct flist far *fexpel OF((struct flist far *));
- X char *in2ex OF((char *));
- X int exclude OF((void));
- X int procname OF((char *));
- X void stamp OF((char *, ulg));
- X ulg dostime OF((int, int, int, int, int, int));
- X ulg filetime OF((char *, ulg *, long *));
- X int issymlnk OF((ulg a));
- X# ifdef S_IFLNK
- X# define rdsymlnk(p,b,n) readlink(p,b,n)
- X extern int readlink OF((char *, char *, int));
- X# else /* !S_IFLNK */
- X# define rdsymlnk(p,b,n) (0)
- X# endif /* !S_IFLNK */
- X int deletedir OF((char *));
- X#endif /* !UTIL */
- int destroy OF((char *));
- int replace OF((char *, char *));
- int getfileattr OF((char *));
- int setfileattr OF((char *, int));
- char *tempname OF((int));
- int fcopy OF((FILE *, FILE *, ulg));
- X#ifndef EXPORT
- X# ifndef MSVMS
- X void echoff OF((int));
- X void echon OF((void));
- X# endif /* !MSVMS */
- X char *getp OF((char *, char *, int));
- X#endif /* !EXPORT */
- X#ifdef ZMEM
- X char *memset OF((char *, int, unsigned int));
- X char *memcpy OF((char *, char *, unsigned int));
- X int memcmp OF((char *, char *, unsigned int));
- X#endif /* ZMEM */
- X
- X /* in crypt.c */
- X#ifdef EXPORT
- X# define zfwrite fwrite
- X#else /* !EXPORT */
- X void crypthead OF((char *, ulg, FILE *));
- X# ifdef UTIL
- X int zipcloak OF ((struct zlist far *, FILE *, FILE *, char *));
- X int zipbare OF ((struct zlist far *, FILE *, FILE *, char *));
- X# else /* !UTIL */
- X int zfwrite OF((voidp *, extent, extent, FILE *));
- X int zfputc OF((int, FILE *));
- X# endif /* ?UTIL */
- X#endif /* ?EXPORT */
- X
- X /* in util.c */
- char *isshexp OF((char *));
- int shmatch OF((char *, char *));
- X#ifdef MSDOS
- X int dosmatch OF((char *, char *));
- X#endif /* MSDOS */
- voidp far **search OF((voidp *, voidp far **, extent,
- X int (*)(voidp *, voidp far *)));
- ulg crc32 OF((ulg, int));
- ulg updcrc OF((char *, extent));
- X
- X /* in shrink.c */
- X#ifndef UTIL
- X int shr_setup OF((void));
- X int shr_p1 OF((uch *, extent));
- X int shr_size OF((ulg *));
- X int shr_p2 OF((FILE *));
- X int shr_clear OF((void));
- X
- X /* in implode.c */
- X# ifndef NOIMPLODE
- X int imp_setup OF((long, int));
- X int imp_p1 OF((char *, int));
- X int imp_size OF((ulg *, uch *));
- X int imp_p2 OF((FILE *));
- X int imp_clear OF((void));
- X# endif /* !NOIMPLODE */
- X#endif /* !UTIL */
- X
- X
- X/* end of zip.h */
- END_OF_FILE
- if test 8017 -ne `wc -c <'zip.h'`; then
- echo shar: \"'zip.h'\" unpacked with wrong size!
- fi
- # end of 'zip.h'
- fi
- if test -f 'zipnote.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zipnote.c'\"
- else
- echo shar: Extracting \"'zipnote.c'\" \(9810 characters\)
- sed "s/^X//" >'zipnote.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * zipnote.c by Mark Adler.
- X */
- X
- X#define UTIL
- X#include "revision.h"
- X#include "zip.h"
- X#include <signal.h>
- X
- X
- X/* Character to mark zip entry names in the comment file */
- X#define MARK '@'
- X
- X/* Temporary zip file name and file pointer */
- local char *tempzip;
- local FILE *tempzf;
- X
- X
- X/* Local functions */
- X#ifdef PROTO
- X local void err(int, char *);
- X local void handler(int);
- X local void license(void);
- X local void help(void);
- X local void putclean(char *);
- X local int catalloc(char * far *, char *);
- X void main(int, char **);
- X#endif /* PROTO */
- X
- X
- X
- local void err(c, h)
- int c; /* error code from the ZE_ class */
- char *h; /* message about how it happened */
- X/* Issue a message for the error, clean up files and memory, and exit. */
- X{
- X if (PERR(c))
- X perror("zipnote error");
- X fprintf(stderr, "zipnote error: %s (%s)\n", errors[c-1], h);
- X if (tempzf != NULL)
- X fclose(tempzf);
- X if (tempzip != NULL)
- X {
- X destroy(tempzip);
- X free((voidp *)tempzip);
- X }
- X if (zipfile != NULL)
- X free((voidp *)zipfile);
- X#ifdef VMS
- X exit(0);
- X#else /* !VMS */
- X exit(c);
- X#endif /* ?VMS */
- X}
- X
- X
- local void handler(s)
- int s; /* signal number (ignored) */
- X/* Upon getting a user interrupt, abort cleanly using err(). */
- X{
- X#ifndef MSDOS
- X putc('\n', stderr);
- X#endif /* !MSDOS */
- X err(ZE_ABORT, "aborting");
- X s++; /* keep some compilers happy */
- X}
- X
- X
- void warn(a, b)
- char *a, *b; /* message strings juxtaposed in output */
- X/* Print a warning message to stderr and return. */
- X{
- X fprintf(stderr, "zipnote warning: %s%s\n", a, b);
- X}
- X
- X
- local void license()
- X/* Print license information to stdout. */
- X{
- X extent i; /* counter for copyright array */
- X
- X for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
- X puts(copyright[i]);
- X for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
- X puts(disclaimer[i]);
- X}
- X
- X
- local void help()
- X/* Print help (along with license info) to stdout. */
- X{
- X extent i; /* counter for help array */
- X
- X /* help array */
- X static char *text[] = {
- X"",
- X"ZipNote %d.%d (%s)",
- X"Usage: zipnote [-w] [-b path] zipfile",
- X" the default action is to write the comments in zipfile to stdout",
- X" -w write the zipfile comments from stdin",
- X" -b use \"path\" for the temporary zip file",
- X" -h show this help -l show software license",
- X"",
- X"Example:",
- X#ifdef VMS
- X" define/user sys$output foo.tmp",
- X" zipnote foo.zip",
- X" edit foo.tmp",
- X" ... then you edit the comments, save, and exit ...",
- X" define/user sys$input foo.tmp",
- X" zipnote -w foo.zip"
- X#else /* !VMS */
- X" zipnote foo.zip > foo.tmp",
- X" ed foo.tmp",
- X" ... then you edit the comments, save, and exit ...",
- X" zipnote -w foo.zip < foo.tmp"
- X#endif /* ?VMS */
- X };
- X
- X for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
- X puts(copyright[i]);
- X for (i = 0; i < sizeof(text)/sizeof(char *); i++)
- X {
- X printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
- X putchar('\n');
- X }
- X}
- X
- X
- local void putclean(s)
- char *s; /* string to write to stdout */
- X/* Write the string s to stdout, filtering out control characters that are
- X not tab or newline (mainly to remove carriage returns), and prefix MARK's
- X and backslashes with a backslash. Also, terminate with a newline if
- X needed. */
- X{
- X int c; /* next character in string */
- X int e; /* last character written */
- X
- X e = '\n'; /* if empty, write nothing */
- X while ((c = *s++) != 0)
- X {
- X if (c == MARK || c == '\\')
- X putchar('\\');
- X if (c >= ' ' || c == '\t' || c == '\n')
- X putchar(e = c);
- X }
- X if (e != '\n')
- X putchar('\n');
- X}
- X
- X
- local int catalloc(a, s)
- char * far *a; /* pointer to a pointer to a malloc'ed string */
- char *s; /* string to concatenate on a */
- X/* Concatentate the string s to the malloc'ed string pointed to by a.
- X Preprocess s by removing backslash escape characters. */
- X{
- X char *p; /* temporary pointer */
- X char *q; /* temporary pointer */
- X
- X for (p = q = s; *q; *p++ = *q++)
- X if (*q == '\\' && *(q+1))
- X q++;
- X *p = 0;
- X if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)
- X return ZE_MEM;
- X strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);
- X free((voidp *)*a);
- X *a = p;
- X return ZE_OK;
- X}
- X
- X
- void main(argc, argv)
- int argc; /* number of tokens in command line */
- char **argv; /* command line tokens */
- X/* Write the comments in the zipfile to stdout, or read them from stdin. */
- X{
- X char a[FNMAX+1]; /* input line buffer */
- X ulg c; /* start of central directory */
- X int k; /* next argument type */
- X char *q; /* steps through option arguments */
- X int r; /* arg counter, temporary variable */
- X ulg s; /* length of central directory */
- X int t; /* attributes of zip file */
- X int w; /* true if updating zip file from stdin */
- X FILE *x, *y; /* input and output zip files */
- X struct zlist far *z; /* steps through zfiles linked list */
- X
- X
- X /* If no args, show help */
- X if (argc == 1)
- X {
- X help();
- X exit(0);
- X }
- X
- X /* Go through args */
- X zipfile = tempzip = NULL;
- X tempzf = NULL;
- X signal(SIGINT, handler);
- X signal(SIGTERM, handler);
- X k = w = 0;
- X for (r = 1; r < argc; r++)
- X if (*argv[r] == '-')
- X if (argv[r][1])
- X for (q = argv[r]+1; *q; q++)
- X switch(*q)
- X {
- X case 'b': /* Specify path for temporary file */
- X if (k)
- X err(ZE_PARMS, "use -b before zip file name");
- X else
- X k = 1; /* Next non-option is path */
- X break;
- X case 'h': /* Show help */
- X help(); exit(0);
- X case 'l': /* Show copyright and disclaimer */
- X license(); exit(0);
- X case 'w':
- X w = 1; break;
- X default:
- X err(ZE_PARMS, "unknown option");
- X }
- X else
- X err(ZE_PARMS, "zip file cannot be stdin");
- X else
- X if (k == 0)
- X if (zipfile == NULL)
- X {
- X if ((zipfile = ziptyp(argv[r])) == NULL)
- X err(ZE_MEM, "was processing arguments");
- X }
- X else
- X err(ZE_PARMS, "can only specify one zip file");
- X else
- X {
- X tempath = argv[r];
- X k = 0;
- X }
- X if (zipfile == NULL)
- X err(ZE_PARMS, "need to specify zip file");
- X
- X /* Read zip file */
- X if ((r = readzipfile()) != ZE_OK)
- X err(r, zipfile);
- X if (zfiles == NULL)
- X err(ZE_NAME, zipfile);
- X
- X /* Put comments to stdout, if not -u */
- X if (!w)
- X {
- X for (z = zfiles; z != NULL; z = z->nxt)
- X {
- X printf("%c %s\n", MARK, z->zname);
- X if (z->com)
- X putclean(z->comment);
- X putchar(MARK); putchar('\n');
- X }
- X putchar(MARK); putchar('\n');
- X if (zcomlen)
- X putclean(zcomment);
- X exit(ZE_OK);
- X }
- X
- X /* If updating comments, make sure zip file is writeable */
- X if ((x = fopen(zipfile, "a")) == NULL)
- X err(ZE_CREAT, zipfile);
- X fclose(x);
- X t = getfileattr(zipfile);
- X
- X /* Process stdin, replacing comments */
- X for (z = zfiles; z != NULL; z = z->nxt)
- X {
- X if (gets(a) == NULL || a[0] != MARK || a[1] != ' ' ||
- X strcmp(a + 2, z->zname))
- X err(ZE_NOTE, "missing entry name");
- X if (z->com)
- X free((voidp *)z->comment);
- X z->comment = malloc(1); *(z->comment) = 0;
- X while (gets(a) != NULL && *a != MARK)
- X if ((r = catalloc(&(z->comment), a)) != ZE_OK)
- X err(r, "was building new comments");
- X if (a[1])
- X err(ZE_NOTE, "missing comment end line");
- X z->com = strlen(z->comment);
- X }
- X if (gets(a) == NULL || a[0] != MARK || a[1])
- X err(ZE_NOTE, "missing zip file comment marker line");
- X zcomment = malloc(1); *zcomment = 0;
- X while (gets(a) != NULL)
- X if ((r = catalloc(&zcomment, a)) != ZE_OK)
- X err(r, "was building new comments");
- X zcomlen = strlen(zcomment);
- X
- X /* Open output zip file for writing */
- X if ((tempzf = y = fopen(tempzip = tempname('Z'), FOPW)) == NULL)
- X err(ZE_TEMP, tempzip);
- X
- X /* Open input zip file again, copy preamble if any */
- X if ((x = fopen(zipfile, FOPR)) == NULL)
- X err(ZE_NAME, zipfile);
- X if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
- X err(r, r == ZE_TEMP ? tempzip : zipfile);
- X
- X /* Go through local entries, copying them over as is */
- X for (z = zfiles; z != NULL; z = z->nxt)
- X if ((r = zipcopy(z, x, y)) != ZE_OK)
- X err(r, "was copying an entry");
- X fclose(x);
- X
- X /* Write central directory and end of central directory with new comments */
- X if ((c = ftell(y)) == -1L) /* get start of central */
- X err(ZE_TEMP, tempzip);
- X for (z = zfiles; z != NULL; z = z->nxt)
- X if ((r = putcentral(z, y)) != ZE_OK)
- X err(r, tempzip);
- X if ((s = ftell(y)) == -1L) /* get end of central */
- X err(ZE_TEMP, tempzip);
- X s -= c; /* compute length of central */
- X if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)
- X err(r, tempzip);
- X tempzf = NULL;
- X if (fclose(y))
- X err(ZE_TEMP, tempzip);
- X if ((r = replace(zipfile, tempzip)) != ZE_OK)
- X {
- X warn("new zip file left as: ", tempzip);
- X free((voidp *)tempzip);
- X tempzip = NULL;
- X err(r, "was replacing the original zip file");
- X }
- X free((voidp *)tempzip);
- X tempzip = NULL;
- X setfileattr(zipfile, t);
- X free((voidp *)zipfile);
- X zipfile = NULL;
- X
- X /* Done! */
- X exit(ZE_OK);
- X}
- END_OF_FILE
- if test 9810 -ne `wc -c <'zipnote.c'`; then
- echo shar: \"'zipnote.c'\" unpacked with wrong size!
- fi
- # end of 'zipnote.c'
- fi
- if test -f 'zipup.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zipup.c'\"
- else
- echo shar: Extracting \"'zipup.c'\" \(10409 characters\)
- sed "s/^X//" >'zipup.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * zipup.c by Mark Adler.
- X */
- X
- X#define NOCPYRT /* this is not a main module */
- X#include "zip.h"
- X#include "revision.h"
- X
- X/* Use the raw functions for MSDOS and Unix to save on buffer space.
- X They're not used for VMS since it doesn't work (raw is weird on VMS).
- X (This sort of stuff belongs in fileio.c, but oh well.) */
- X#ifdef VMS
- X typedef FILE *ftype;
- X# define fhow FOPR
- X# define fbad NULL
- X# define zopen(n,p) fopen(n,p)
- X# define zread(f,b,n) fread(b,1,n,f)
- X# define zclose(f) fclose(f)
- X# define zerr(f) ferror(f)
- X# define zrew(f) rewind(f)
- X#else /* !VMS */
- X# ifdef MSDOS
- X# include <io.h>
- X# include <fcntl.h>
- X# define fhow (O_RDONLY|O_BINARY)
- X# else /* !MSDOS */
- X int open OF((char *, int));
- X int read OF((int, char *, int));
- X int close OF((int));
- X int lseek OF((int,long,int));
- X# define fhow 0
- X# endif /* ?MSDOS */
- X typedef int ftype;
- X# define fbad (-1)
- X# define zopen(n,p) open(n,p)
- X# define zread(f,b,n) read(f,b,n)
- X# define zclose(f) close(f)
- X# define zerr(f) (k<0)
- X# define zrew(f) lseek(f,0L,0)
- X#endif /* ?VMS */
- X
- X
- X/* Local functions */
- X#ifdef PROTO
- X# ifndef UTIL
- X local int suffixes(char *, char *);
- X# endif /* !UTIL */
- X#endif /* PROTO */
- X
- X
- X/* Note: a zip "entry" includes a local header (which includes the file
- X name), an encryption header if encrypting, and the compressed data. */
- X
- X
- int zipcopy(z, x, y)
- struct zlist far *z; /* zip entry to copy */
- XFILE *x, *y; /* source and destination files */
- X/* Copy the zip entry described by *z from file *x to file *y. Return an
- X error code in the ZE_ class. */
- X{
- X ulg n; /* holds local header offset */
- X
- X if (fseek(x, z->off, SEEK_SET))
- X return ferror(x) ? ZE_READ : ZE_EOF;
- X if ((n = ftell(y)) == -1L)
- X return ZE_TEMP;
- X z->off = n;
- X n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
- X return fcopy(x, y, n);
- X}
- X
- X
- X#ifndef UTIL
- X
- int percent(n, m)
- ulg n, m; /* n is the original size, m is the new size */
- X/* Return the percentage compression from n to m using only integer
- X operations */
- X{
- X if (n > 0xffffffL) /* If n >= 16M */
- X { /* then divide n and m by 256 */
- X n += 0x80; n >>= 8;
- X m += 0x80; m >>= 8;
- X }
- X return n ? (int)(1 + (200 * (n - m))/n) >> 1 : 0;
- X}
- X
- X
- local int suffixes(a, s)
- char *a; /* name to check suffix of */
- char *s; /* list of suffixes separated by : or ; */
- X/* Return true if a ends in any of the suffixes in the list s. */
- X{
- X int m; /* true if suffix matches so far */
- X char *p; /* pointer into special */
- X char *q; /* pointer into name a */
- X
- X m = 1;
- X q = a + strlen(a) - 1;
- X for (p = s + strlen(s) - 1; p >= s; p--)
- X if (*p == ':' || *p == ';')
- X if (m)
- X return 1;
- X else
- X {
- X m = 1;
- X q = a + strlen(a) - 1;
- X }
- X else
- X#ifdef OS2
- X {
- X m = m && q >= a && tolower(*p) == tolower(*q);
- X q--;
- X }
- X#else /* !OS2 */
- X m = m && q >= a && *p == *q--;
- X#endif /* ?OS2 */
- X return m;
- X}
- X
- X
- int zipup(z, y)
- struct zlist far *z; /* zip entry to compress */
- XFILE *y; /* output file */
- X/* Compress the file z->name into the zip entry described by *z and write
- X it to the file *y. Determine the best method (store, shrink, or implode)
- X and use it. Encrypt if requested. Return an error code in the
- X ZE_ class. */
- X{
- X ulg a; /* attributes returned by filetime() */
- X char *b; /* malloc'ed file buffer */
- X ulg c; /* crc on uncompressed file data */
- X ftype f; /* file to compress */
- X uch g; /* flags returned by implode */
- X int h; /* compression method chosen (how) */
- X#ifndef NOIMPLODE
- X ulg i; /* size of imploded data */
- X#endif /* !NOIMPLODE */
- X extent k; /* result of zread */
- X int l; /* true if this file is a symbolic link */
- X int m; /* method for this entry */
- X ulg n; /* size of uncompressed file */
- X long q; /* size returned by filetime */
- X int r; /* temporary variable */
- X ulg s; /* size of shrunk or compressed data */
- X
- X /* Open file to zip up */
- X if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < 0)
- X return ZE_OPEN;
- X l = issymlnk(a);
- X if (l)
- X f = fbad;
- X else if ((f = zopen(z->name, fhow)) == fbad)
- X return ZE_OPEN;
- X
- X /* Select method based on the suffix and the global method */
- X m = special != NULL && suffixes(z->name, special) ? STORE : method;
- X
- X /* Don't bother with shrink for "large" files (320 is what PKZIP uses--the
- X number used here must be <= BSZ) */
- X if (m == BEST && q > 512)
- X m = IMPLODE;
- X if (q == 0)
- X m = STORE;
- X
- X /* Make first pass on the file, computing the crc and length, and running
- X shrink and implode on it. */
- X n = 0;
- X c = updcrc((char *)NULL, 0);
- X if ((b = malloc(BSZ)) == NULL)
- X return ZE_MEM;
- X if (m == BEST || m == SHRINK)
- X if ((r = shr_setup()) != ZE_OK)
- X return r;
- X else
- X shract = 1;
- X while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
- X {
- X n += k;
- X c = updcrc(b, k);
- X#ifdef MINIX
- X if (l)
- X q = k;
- X#endif /* MINIX */
- X if ((m == BEST || m == SHRINK) && (r = shr_p1((uch *)b, k)) != ZE_OK)
- X {
- X free((voidp *)b);
- X shr_clear();
- X shract = 0;
- X return r;
- X }
- X if (m == BEST) /* free up shrink data structures */
- X {
- X if ((!l && zread(f, b, BSZ) != 0)
- X#ifndef VMS
- X || n != (ulg)q
- X#endif /* !VMS */
- X )
- X return ZE_READ;
- X if ((r = shr_size(&s)) != ZE_OK)
- X {
- X shr_clear();
- X shract = 0;
- X return r;
- X }
- X }
- X#ifndef NOIMPLODE
- X if (m == BEST || m == IMPLODE)
- X {
- X if (!impact)
- X if ((r = imp_setup(q, level)) != ZE_OK)
- X return r;
- X else
- X impact = 1;
- X if ((r = imp_p1(b, k)) != ZE_OK)
- X {
- X free((voidp *)b);
- X imp_clear();
- X impact = 0;
- X return r;
- X }
- X }
- X#endif /* !NOIMPLODE */
- X if (m == BEST || l)
- X break;
- X }
- X free((voidp *)b);
- X if (!l && zerr(f))
- X return ZE_READ;
- X
- X /* Determine the best method to use */
- X g = 0;
- X if (noisy && verbose)
- X printf(" (n=%lu)", n);
- X if (m == SHRINK && (r = shr_size(&s)) != ZE_OK)
- X {
- X shr_clear();
- X shract = 0;
- X return r;
- X }
- X if (noisy && verbose && (m == BEST || m == SHRINK))
- X printf(" (s=%lu)", s);
- X#ifndef NOIMPLODE
- X if ((m == BEST || m == IMPLODE) && (r = imp_size(&i, &g)) != ZE_OK)
- X {
- X imp_clear();
- X impact = 0;
- X return r;
- X }
- X if (noisy && verbose && (m == BEST || m == IMPLODE))
- X printf(" (i=%lu)", i);
- X if ((m == BEST || m == IMPLODE) && i < n && (m == IMPLODE || i < s))
- X {
- X if (noisy)
- X {
- X printf(" (imploded %d%%)", percent(n, i));
- X fflush(stdout);
- X }
- X h = IMPLODE;
- X s = i;
- X if (m == BEST)
- X {
- X shr_clear();
- X shract = 0;
- X }
- X if (!l)
- X zclose(f);
- X }
- X else
- X#endif /* !NOIMPLODE */
- X if ((m == BEST || m == SHRINK) && s < n)
- X {
- X if (noisy)
- X {
- X printf(" (shrunk %d%%)", percent(n, s));
- X fflush(stdout);
- X }
- X h = SHRINK;
- X#ifndef NOIMPLODE
- X if (m == BEST)
- X {
- X imp_clear();
- X impact = 0;
- X }
- X#endif /* !NOIMPLODE */
- X if (!l)
- X zclose(f);
- X }
- X else
- X {
- X if (noisy)
- X {
- X printf(" (stored 0%%)");
- X fflush(stdout);
- X }
- X h = STORE;
- X s = n;
- X#ifndef NOIMPLODE
- X if (m == BEST || m == IMPLODE)
- X {
- X imp_clear();
- X impact = 0;
- X }
- X#endif /* !NOIMPLODE */
- X if (m == BEST || m == SHRINK)
- X {
- X shr_clear();
- X shract = 0;
- X }
- X }
- X
- X#ifndef VMS
- X /* Check size (but not in VMS--variable record lengths mess it up) */
- X if (n != (ulg)q)
- X return ZE_READ;
- X#endif /* !VMS */
- X
- X /* Fill in header information and write local header to zip file */
- X#ifdef OS2
- X if ( dosify < 2 )
- X dosify = IsFileSystemFAT(z->name);
- X#endif /* OS2 */
- X
- X /* (Assume ext, cext, com, and zname already filled in.) */
- X z->vem = dosify ? 11 : /* Made under MSDOS by PKZIP 1.1 */
- X#ifdef VMS
- X 0x200 + REVISION; /* Made under VMS by this Zip */
- X#else /* !VMS */
- X#ifdef OS2
- X 0x600 + REVISION; /* Made under OS/2 by this Zip */
- X#else /* !OS2 */
- X 0x300 + REVISION; /* Made under Unix by this Zip */
- X#endif /* ?OS2 */
- X#endif /* ?VMS */
- X z->ver = 10; /* Need PKUNZIP 1.0 */
- X z->flg = (ush)g;
- X if (key != NULL)
- X z->flg |= 1;
- X z->lflg = z->flg;
- X z->how = h;
- X z->crc = c;
- X z->siz = s;
- X if (key != NULL)
- X z->siz += 12;
- X z->len = n;
- X z->nam = strlen(z->zname);
- X z->dsk = 0;
- X z->att = 0; /* Assume they're all binary */
- X z->atx = dosify ? a & 0xff : a; /* Attributes from filetime() */
- X if ((z->off = ftell(y)) == -1L)
- X return ZE_WRITE;
- X if ((r = putlocal(z, y)) != ZE_OK)
- X return r;
- X
- X /* Write stored, shrunk, or imploded file to zip file */
- X#ifndef EXPORT
- X if (key != NULL)
- X crypthead(key, z->crc, y);
- X#endif /* !EXPORT */
- X n = ftell(y); /* Save offset for logic check */
- X#ifndef NOIMPLODE
- X if (h == IMPLODE)
- X {
- X if ((r = imp_p2(y)) != ZE_OK)
- X return r;
- X imp_clear();
- X impact = 0;
- X }
- X else
- X#endif /* !NOIMPLODE */
- X if (h == SHRINK)
- X {
- X if ((r = shr_p2(y)) != ZE_OK)
- X return r;
- X shr_clear();
- X shract = 0;
- X }
- X else
- X {
- X if (!l)
- X zrew(f);
- X if ((b = malloc(BSZ)) == NULL)
- X return ZE_MEM;
- X while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
- X {
- X if (zfwrite(b, 1, k, y) != k)
- X {
- X free((voidp *)b);
- X return ZE_TEMP;
- X }
- X if (l)
- X break;
- X }
- X free((voidp *)b);
- X if (!l && zerr(f))
- X return ZE_READ;
- X if (!l)
- X zclose(f);
- X }
- X
- X /* Check length of compressed data */
- X if (ftell(y) != n + s)
- X return ZE_LOGIC;
- X
- X /* Done--clean up and leave */
- X if (noisy)
- X {
- X putchar('\n');
- X fflush(stdout);
- X }
- X return ZE_OK;
- X}
- X
- X#endif /* !UTIL */
- END_OF_FILE
- if test 10409 -ne `wc -c <'zipup.c'`; then
- echo shar: \"'zipup.c'\" unpacked with wrong size!
- fi
- # end of 'zipup.c'
- fi
- echo shar: End of archive 2 \(of 7\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-